package com.jd.jobkeeper.server.service.db.impl;

import com.jd.jobkeeper.server.data.entity.Namespace;
import com.jd.jobkeeper.server.data.entity.ServerInfo;
import com.jd.jobkeeper.server.data.pesistence.NamespaceRepository;
import com.jd.jobkeeper.server.service.NamespaceService;
import com.jd.jobkeeper.server.service.ServerInfoService;
import org.hibernate.StaleObjectStateException;
import org.springframework.stereotype.Service;


@Service
public class DBNamespaceServiceImpl implements NamespaceService {

    final NamespaceRepository namespaceRepository;
    final ServerInfoService serverInfoService;

    public DBNamespaceServiceImpl(NamespaceRepository namespaceRepository,
                                  ServerInfoService serverInfoService) {
        this.namespaceRepository = namespaceRepository;
        this.serverInfoService = serverInfoService;
    }

    @Override
    public Namespace add(Namespace namespace) {
        return this.namespaceRepository.saveAndFlush(namespace);
    }

    @Override
    public Namespace discoveryLeader(String nsCode, String appName) {
        Namespace namespace = namespaceRepository.findByCode(nsCode);
        if (namespace == null) {
            throw new RuntimeException("Namespace " + nsCode + " is not exist!");
        }

        String serverId = namespace.getServerId();
        if (serverInfoService.isSelf(serverId) || serverInfoService.isAlive(serverId)) {
            return namespace;
        }
        return takeNamespace(namespace);
    }

    private Namespace takeNamespace(Namespace namespace) {
        ServerInfo serverInfo = serverInfoService.currentServer();
        namespace.setHost(serverInfo.getHost());
        namespace.setPort(serverInfo.getPort());
        namespace.setServerId(serverInfo.getServerId());
        namespace.setModifyTime(System.currentTimeMillis());

        try {
            return namespaceRepository.saveAndFlush(namespace);
        } catch (StaleObjectStateException se) {
            //Other node get the namespace's leader
            return namespaceRepository.findById(namespace.getId()).get();
        }
    }
}
